package com.yubest;

/**
 * 给你一个单链表的头节点 head ，请你判断该链表是否为回文链表。如果是，返回 true ；否则，返回 false 。
 *
 *  
 *
 * 示例 1：[图片] img/0234_1.jpg
 *
 *
 * 输入：head = [1,2,2,1]
 * 输出：true
 *
 * 示例 2：[图片] img/0234_2.jpg
 *
 *
 * 输入：head = [1,2]
 * 输出：false
 *  
 *
 * 提示：
 *
 * 链表中节点数目在范围[1, 10^5] 内
 * 0 <= Node.val <= 9
 *  
 *
 * 进阶：你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题？
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/palindrome-linked-list
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 *
 * @Author hweiyu
 * @Description
 * @Date 2021/12/17 16:39
 */
public class P0234 {

    public static void main(String[] args) {
        System.out.println(new Solution234().isPalindrome(
                new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(2, new ListNode(1)))))));
    }
}

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution234 {

    public boolean isPalindrome(ListNode head) {
        //记录一共有几个节点
        int n = 0;
        ListNode cur = head;
        while (cur != null) {
            n++;
            cur = cur.next;
        }
        if (n == 1) {
            return true;
        }
        cur = head;
        //前半段链表的最尾一个节点
        ListNode firstTail = head;
        for (int i = 0; i < n / 2; i++) {
            firstTail = cur;
            cur = cur.next;
        }
        ListNode p1 = head;
        //将后半段链表进行反转链表
        ListNode t = reverse(cur);
        ListNode p2 = t;
        boolean isPalindrome = true;
        for (int i = 0; i < n / 2; i++) {
            if (p1.val != p2.val) {
                isPalindrome = false;
                break;
            }
            p1 = p1.next;
            p2 = p2.next;
        }
        //链表恢复原样
        firstTail.next = reverse(t);
        return isPalindrome;
    }

    private ListNode reverse(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        ListNode next = null;
        while (cur != null) {
            next = cur.next;
            cur.next = pre;
            if (next == null) {
                break;
            }
            pre = cur;
            cur = next;
        }
        return cur;
    }
}
